gdk/wayland: cope with the compositor implementing an older protocol than us
authorGiovanni Campagna <gcampagn@redhat.com>
Fri, 12 Jul 2013 14:49:52 +0000 (16:49 +0200)
committerGiovanni Campagna <gcampagn@redhat.com>
Tue, 16 Jul 2013 16:19:08 +0000 (18:19 +0200)
If we bind to a global with an higher version than implemented, or
we make requests that appeared in a later version, we would get
fatal wayland errors.

https://bugzilla.gnome.org/show_bug.cgi?id=704104

gdk/wayland/gdkdisplay-wayland.c
gdk/wayland/gdkdisplay-wayland.h
gdk/wayland/gdkwindow-wayland.c

index cf3d812779531bd1afbf40425631316f038156d0..7d748e05a2673ab3196d3ea4acc66a50d64cfe70 100644 (file)
@@ -156,7 +156,8 @@ gdk_registry_handle_global(void *data, struct wl_registry *registry, uint32_t id
 
   if (strcmp(interface, "wl_compositor") == 0) {
     display_wayland->compositor =
-       wl_registry_bind(display_wayland->wl_registry, id, &wl_compositor_interface, 3);
+      wl_registry_bind(display_wayland->wl_registry, id, &wl_compositor_interface, MIN (version, 3));
+    display_wayland->compositor_version = MIN (version, 3);
   } else if (strcmp(interface, "wl_shm") == 0) {
    display_wayland->shm =
        wl_registry_bind(display_wayland->wl_registry, id, &wl_shm_interface, 1);
@@ -168,8 +169,8 @@ gdk_registry_handle_global(void *data, struct wl_registry *registry, uint32_t id
        wl_registry_bind(display_wayland->wl_registry, id, &wl_shell_interface, 1);
   } else if (strcmp(interface, "wl_output") == 0) {
     output =
-      wl_registry_bind(display_wayland->wl_registry, id, &wl_output_interface, 2);
-    _gdk_wayland_screen_add_output(display_wayland->screen, id, output, version);
+      wl_registry_bind(display_wayland->wl_registry, id, &wl_output_interface, MIN (version, 2));
+    _gdk_wayland_screen_add_output(display_wayland->screen, id, output, MIN (version, 2));
     /* We need another roundtrip to receive the modes and geometry
      * events for the output, which gives us the physical properties
      * and available modes on the output. */
index 35eac41a3d8f6029ac3f9b747ecfca9c52f63cec..50f41fa6f7bf07919a17e2a876668d1287da8e3b 100644 (file)
@@ -67,6 +67,7 @@ struct _GdkWaylandDisplay
   GSource *event_source;
 
   int init_ref_count;
+  int compositor_version;
 
   struct xkb_context *xkb_context;
 };
index 5e282e5ea526bbb8ea56241b604871322bce8940..f4db8daa30cbfce25c0b4dc901f393dcccb19e99 100644 (file)
@@ -37,6 +37,7 @@
 #include <sys/mman.h>
 #include <errno.h>
 
+#define WL_SURFACE_HAS_BUFFER_SCALE 3
 
 #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
@@ -433,6 +434,13 @@ window_update_scale (GdkWindow *window)
   guint32 scale;
   GSList *l;
 
+  if (wayland_display->compositor_version < WL_SURFACE_HAS_BUFFER_SCALE)
+    {
+      /* We can't set the scale on this surface */
+      impl->scale = 1;
+      return;
+    }
+
   scale = 1;
   for (l = impl->outputs; l != NULL; l = l->next)
     {
@@ -538,6 +546,7 @@ _gdk_wayland_display_create_window_impl (GdkDisplay    *display,
 static void
 gdk_wayland_window_attach_image (GdkWindow *window)
 {
+  GdkWaylandDisplay *display;
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
   GdkWaylandCairoSurfaceData *data;
   int32_t server_width, server_height, dx, dy;
@@ -584,7 +593,11 @@ gdk_wayland_window_attach_image (GdkWindow *window)
 
   /* Attach this new buffer to the surface */
   wl_surface_attach (impl->surface, data->buffer, dx, dy);
-  wl_surface_set_buffer_scale (impl->surface, data->scale);
+
+  /* Only set the buffer scale if supported by the compositor */
+  display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
+  if (display->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE)
+    wl_surface_set_buffer_scale (impl->surface, data->scale);
 
   impl->pending_commit = TRUE;
 }